/************************************************************************
Copyright (c) 2010, 2013, C.R. All rights reserved. 

E-mail: crtoyou@gmail.com; crtoyou@163.com

You can redistribute it and/or modify it under the terms of the
GNU Lesser General Public License as published by the
Free Software Foundation version 3 of the License.

This source code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program. if not, write to the Free Software Foundation, Inc., 
51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
************************************************************************/

#ifndef __CR_HASH_STRING_TO_STRING_H__
#define __CR_HASH_STRING_TO_STRING_H__

#include <wincrypt.h>
#include <vector>
#pragma comment(lib, "Crypt32.lib")


class CCryptHash
{
public:
	CCryptHash()
	{
		if(!CryptAcquireContextA(&m_hCryptProv, "CrCSP_2011", MS_ENHANCED_PROV_A , PROV_RSA_FULL, 0) && 
			!CryptAcquireContextA(&m_hCryptProv, "CrCSP_2011", MS_ENHANCED_PROV_A , PROV_RSA_FULL, CRYPT_NEWKEYSET))
		{	m_hCryptProv = NULL;
		}
	}
	~CCryptHash(void)
	{
		if(!m_hCryptProv) 
			return;
		CryptReleaseContext(m_hCryptProv, 0);
	}
	BOOL Hash(const BYTE dataIn[], DWORD lenIn, std::vector<BYTE>& vecOut, ALG_ID Algid = CALG_MD5)
	{
		if (!m_hCryptProv)
			return FALSE;
		HCRYPTHASH hHash = NULL;
		if (!CryptCreateHash(m_hCryptProv, Algid, 0, 0, &hHash))
			return FALSE;
		if (!CryptHashData(hHash, dataIn, lenIn, 0))
			return FALSE;
		DWORD dwHashLen = 0;
		if (!CryptGetHashParam(hHash, HP_HASHVAL, NULL, &dwHashLen, 0)) 
			return FALSE;
		vecOut.resize(dwHashLen);
		if (!CryptGetHashParam(hHash, HP_HASHVAL, &vecOut[0], &dwHashLen, 0)) 
			return FALSE;
		return TRUE;
	}
	BOOL Hash(std::vector<BYTE>& vecInOut, ALG_ID Algid = CALG_MD5)
	{	return Hash(&vecInOut[0], vecInOut.size(), vecInOut, Algid);
	}
private:
	HCRYPTPROV m_hCryptProv;
};


#endif //__CR_HASH_STRING_TO_STRING_H__